package ee122Networking;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.sql.Timestamp;
import java.lang.Object;

import cern.jet.random.Poisson;
import cern.jet.random.engine.DRand;

public class ClientSenderThread extends Thread {

	static int PACKET_DATA_LENGTH = 128; 
	private Poisson poissonGenerator;
	private int routerPort;
	private String routerAddr;
	private String imgPath = null;
	private int numPackets;
	
	
	public ClientSenderThread(int interPacketTime, String routerAddr, int routerPort, int numPackets ){
		poissonGenerator = new Poisson(interPacketTime, new DRand((int)System.currentTimeMillis()));

		this.routerPort = routerPort;
		this.routerAddr = routerAddr;
		this.numPackets = numPackets;
		
	}
	
	
	public ClientSenderThread(int interPacketTime, String routerAddr, String imgPath, int routerPort ){
		poissonGenerator = new Poisson(interPacketTime, new DRand((int)System.currentTimeMillis()));
		
	}
	
	public void run(){
		
		InetAddress address = null;
		DatagramSocket socket = null;
		try {
			
			address = InetAddress.getByName(routerAddr);
			socket= new DatagramSocket();
			
			
			
		} catch (UnknownHostException e) {
			System.out.println(e + "==== cannot resolve "+routerAddr);
			System.exit(1);
		} catch (SocketException e) {
			System.out.println(e + "==== cannot get a socket");
			System.exit(1);
		}

		for(int i=0; i < numPackets; i++){
			
			byte[] sendBuf = new byte[PACKET_DATA_LENGTH];
			fillSendData(sendBuf, i);
		
			DatagramPacket packet = new DatagramPacket(sendBuf, sendBuf.length, address, routerPort);
			
			
			try {
				
				
				socket.send(packet);
				int next = poissonGenerator.nextInt();
				ClientSenderThread.sleep(next);
				
				
			} catch (IOException e) {
				System.out.println(e + "==== cannot send packet");
				System.exit(1);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			
			
		}
		
		socket.close();
				
	}

	private void fillSendData(byte[] sendBuf, int packetNumber) {
			
		if(imgPath==null){
			sendBuf[0] = (byte)packetNumber; //assuming we wont send over 65k + packets 
		}else{
			//TODO:send image data for this packet.. 
			//eg PACKET_DATA_LENGTH * packetNumber to PACKET_DATA_LENGTH * (packetNumber+1) -1 bytes 
		}
		
		//fill in timestamp (last 8 bytes, since it's long)
		//i have no idea why they want us to include this crap info
		Long timestamp = System.currentTimeMillis();
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		DataOutputStream dos = new DataOutputStream(bos);
		try {
			dos.writeLong(timestamp);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			dos.flush();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		byte[] timestampdata = bos.toByteArray();
		int sendBufLength = sendBuf.length;
		System.arraycopy(timestampdata, 0, sendBuf, sendBufLength - 8, 8);
		System.out.println("Sending packet number " + packetNumber + " @ " + new Timestamp(timestamp));		
	}
	
	
}
